// Script Classes.
// ===============

// The Script Abstract Class.
class pp_script {
  int currentFrame, endFrame, currentAction;
  int[] scriptCoords;
  ArrayList <pp_scriptAction> runningChildren;
  HashMap <String, pp_scriptAction[]> children;
  
  pp_script (int EndFrame, int[] ScriptCoords, HashMap <String, pp_scriptAction[]> Children) {
    endFrame = EndFrame;
    scriptCoords = ScriptCoords;
    children = Children;
    runningChildren = new ArrayList<pp_scriptAction>();
  }
  
  // Update Method.
  void update() {
    
    // If current script is still active...
    if ((currentFrame < endFrame) || (runningChildren.size() > 0)) {
    
      // Add new scriptActions to runningChildren.
      pp_scriptAction[] newActions = children.get(str(currentFrame));
      if (newActions != null) {
        for (pp_scriptAction action : newActions) {
          runningChildren.add(action);
        }
      }
    
      // Update actions currently in runningChildren.
      for (int i = 0; i < runningChildren.size(); i++) {
        
        // Get action.
        pp_scriptAction action = runningChildren.get(i);
      
        // Check if action is done.
        if (action.destroyed) {
          action.destroyed = false;
          runningChildren.remove(i);
          i--;
      
        // Else, update.
        } else {
          action.updateAll();
        }
      }
      
      // Update current frame.
      currentFrame++;
    
    // If this script is done, remove it.
    } else { 
      currentFrame = 0;
      pp_currentScript = null;
    }
  }
}

// The scriptAction Abstract Class.
class pp_scriptAction {
  pp_script parent;
  boolean destroyed;
  int currentFrame, endFrame;
  String[] arguments;
  
  pp_scriptAction (String Arguments, pp_script Parent) {
    arguments = split(Arguments, ",");    
    for (int i = 0; i < arguments.length; i++) {arguments[i] = trim(arguments[i]);}    
    parent = Parent;
  }
  
  // Update method.
  void updateAll() {
    
    // Call init() on first frame.
    if (currentFrame == 0) {init();}
    
    // Call update().
    update();
    
    // Progress frame or destroy action.
    if (currentFrame < endFrame) {
      currentFrame++;
    } else {
      destroyed = true;
      currentFrame = 0;
    }
  }
  
  // Client methods.
  void init() {}
  void update() {}
}
  

// Script Functions.
// =================

// Update method for current Script.
void pp_updateScript() {
  if (pp_scriptRunning()) {
    pp_currentScript.update();
  }
}

// Check if a script is running.
boolean pp_scriptRunning() {
  return (pp_currentScript != null) ? true : false;
}

int pp_coordToArray(int x, int y, pp_level level) {
  return x + y * level.levelWidth;
}
